﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Routing;
using System.Reflection;
using System.Web.SessionState;
using AjaxEngines.Serializes;
using AjaxEngines.Reflection;
using AjaxEngines.Extends;

namespace AjaxEngines.JsonHandlers
{
    public class JsonHandlerBase : IHttpHandler, IJsonHandlerEntity, IRequiresSessionState
    {
        public bool ThrowError { get; set; }
        public string InvokeMethodName { get; set; }
        public IJsonHandlerEntity ServiceEntity { get; set; }
        public JsonSerializer JsonSerializer { get; set; }
        public HttpContext Context { get; set; }
        public bool IsReusable
        {
            get { throw new NotImplementedException(); }
        }
        public void ProcessRequest(HttpContext context)
        {
            this.JsonSerializer = new JsonSerializer();
            this.Context = context;
            this.ServiceEntity = this;
            this.InvokeMethodName = context.Request["method"];
            if (this.PreInvoke() && !string.IsNullOrEmpty(this.InvokeMethodName))
            {
                object result = this.InvokeMethod(this.InvokeMethodName);
                context.Response.Clear();
                context.Response.Write(this.JsonSerializer.Serialize(result));
                context.Response.End();
            }
            else
            {
                if (this.ThrowError)
                    throw new Exception("没有指定调用方法");
                else
                {
                    context.Response.Clear();
                    context.Response.Write(this.JsonSerializer.Serialize("没有指定调用方法"));
                    context.Response.End();
                }
            }
        }
        private object InvokeMethod(string methodName)
        {
            try
            {
                MethodInfo methodInfo = MethodCache.GetMethodInfo(this.ServiceEntity.GetType(), methodName);
                if (methodInfo != null && this.IsAjaxMethod(methodInfo))
                {
                    ParameterInfo[] pareameterInfos = ParameterCache.GetPropertyInfo(methodInfo);
                    object[] parameterValueList = this.GetParameterValueList(pareameterInfos);
                    return methodInfo.Invoke(this.ServiceEntity, parameterValueList);
                }
                else if (this.ThrowError)
                    throw new Exception("没有找到指定调用方法");
                else
                {
                    return new Error("没有指定调用方法", "", "");
                }
            }
            catch (Exception e)
            {
                if (this.ThrowError)
                    throw e;
                else
                    return new Error(e.Message, e.Source, e.TargetSite.Name);
            }
        }
        public object[] GetParameterValueList(ParameterInfo[] pareameterInfos)
        {
            List<object> valueList = new List<object>();
            foreach (ParameterInfo pi in pareameterInfos)
            {
                object value = Convert.ToString(this.Context.Request[pi.Name]);
                valueList.Add(value.ConvertTo(pi.ParameterType));
            }
            if (valueList.Count > 0)
                return valueList.ToArray();
            else
                return null;
        }
        private bool IsAjaxMethod(MethodInfo methodInfo)
        {
            object[] attributes = methodInfo.GetCustomAttributes(true);
            foreach (object att in attributes)
                if (att is AjaxMethodAttribute)
                    return true;
            return false;
        }
        public virtual bool PreInvoke()
        {
            return true;
        }
    }
}
